package com.mobimagic.lockscreen.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.os.Build;
import android.os.Handler;
import android.support.v4.view.GestureDetectorCompat;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ScrollView;

import com.mobimagic.lockscreen.AppEnv;
import com.mobimagic.lockscreen.R;
import com.mobimagic.lockscreen.sdk.LockScreenSDK;
import com.mobimagic.lockscreen.util.ScreenUtil;
import com.mobimagic.lockscreen.view.MobileChargingView.CardType;
import com.mobimagic.lockscreen.view.overscroll.OverScroller;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;
import com.nineoldandroids.view.ViewHelper;

@SuppressLint("LongLogTag")
public class MobileChargingScrollView extends ScrollView implements OnGestureListener {

    /**
     * 广告图片的宽高比
     */
    public static final float IMG_WIDTH_HEIGHT = 1.918f;
    private static final int CHECK_SCROLL_DELAY_TIME = 100;

    private static final boolean DEBUG = AppEnv.bAppdebug;
    private static final String TAG = "MobileChargingScrollView";
    private int coverY, showHeadY, showAllY;
    private GestureDetectorCompat gestureDetectorCompat;
    private MobileScrollAdapter mMobileScrollAdapter;
    private float translateHeight;
    private ScrollInfo scrollInfo;
    private float mDownY;
    private float mDownX;
    private boolean needCareMove;
    private OverScroller overScroller;
    private ViewConfiguration configuration;
    private float mLastMotionX, mLastMotionY;
    private LayoutData layoutData;
    private ViewGroup mChildView;
    private Handler handler;
    private View slidingView;
    private boolean needCheckDrageType;
    private boolean isRemoving;
    private boolean isFling = false;
    private DragType dragType = DragType.No;
    private Paint paint;
    private int textPaddingLeft;
    private int paddingTop;
    private boolean onlayouted = false;
    private View checkScrollView = null;

    private enum DragType {
        Slid, VerticalScroll, No;
    }

    public enum CardStatus {
        Null, OneAd, OneOther, MultipleNoScroll, MultipleScroll;
    }

    public MobileChargingScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setVerticalFadingEdgeEnabled(false);
        if (Build.VERSION.SDK_INT >= 14) {
            setOverScrollMode(ScrollView.OVER_SCROLL_NEVER);
        }
        configuration = ViewConfiguration.get(getContext());
        gestureDetectorCompat = new GestureDetectorCompat(getContext(), this);
        scrollInfo = new ScrollInfo();
        overScroller = new OverScroller(context);
        layoutData = LayoutData.getInstance();
        handler = new Handler();
        setWillNotDraw(false);
        paint = new TextPaint();
        paint.setColor(Color.WHITE);
        paint.setTextSize(ScreenUtil.sp2px(getContext(), 16));
        paint.setTextSize(ScreenUtil.sp2px(getContext(), 16));
        textPaddingLeft = ScreenUtil.dpToPxInt(getContext(), 16);
        paddingTop = getResources().getDimensionPixelSize(R.dimen.top_fade_height);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        onlayouted = true;
    }

    private void onLayouted() {
        if (checkScrollView != null) {
            if (mChildView.indexOfChild(checkScrollView) > -1) {
                checkScroll(checkScrollView);
            }
            checkScrollView = null;
        }

    }

    @Override
    public void draw(Canvas canvas) {
        if (onlayouted) {
            onlayouted = false;
            onLayouted();
        }

        if (slidingView != null) {
            CardType cardType = getCardType(slidingView);
            float translateX = ViewHelper.getTranslationX(slidingView);
            String str = "";

            if (translateX != 0) {
                int top = slidingView.getTop();
                int left = 0;
                if (canSlidDelete(slidingView)) {
                    if (translateX > 0) {
                        paint.setTextAlign(Align.LEFT);
                        if (cardType == CardType.AD) {
                            str = LockScreenSDK.getInstance().getString(R.string.app_detail_open);
                        } else {
                            str = LockScreenSDK.getInstance().getString(R.string.delete);
                        }
                        left = textPaddingLeft;
                    } else if (translateX < 0) {
                        str = LockScreenSDK.getInstance().getString(R.string.delete);
                        paint.setTextAlign(Align.RIGHT);
                        left = getMeasuredWidth() - textPaddingLeft;
                    }
                    int scrollY = getScrollY();
                    int expectTop = Math.max(top, scrollY);
                    canvas.drawText(str, left, expectTop + paddingTop + paint.getTextSize(), paint);
                }
            }
        }
        super.draw(canvas);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mChildView = (ViewGroup) getChildAt(0);
    }

    public void addCardViews(final View v, final CardType cardType, LinearLayout.LayoutParams layoutParams) {
        if (v != null) {
            v.setTag(R.id.super_scroll_view, cardType);
            layoutParams.leftMargin = layoutParams.rightMargin = layoutData.getCardMarginLeft();
            mChildView.addView(v, layoutParams);
        } else {
            if (DEBUG) {
                Log.i(TAG, "view为空");
                throw new IllegalArgumentException("v不能为空");
            }
        }
        checkScrollView = v;
    }

    public boolean hasAdCard() {
        if (mChildView != null) {
            int count = mChildView.getChildCount();
            for (int i = 0; i < count; i++) {
                View childCard = mChildView.getChildAt(i);
                CardType cardType = getCardType(childCard);
                if (cardType != null && cardType == cardType.AD) {
                    return true;
                }
            }
        } else {
            if (DEBUG) {
                Log.i(TAG, "mChildView当前为null");
            }
        }
        return false;
    }

    /**
     * 判断是否是广告卡片与其它卡片并存
     *
     * @return
     */
    public boolean isAdInMultipleCards() {
        if (mChildView == null || mChildView.getChildCount() <= 1) {
            return false;
        }
        int count = mChildView.getChildCount();
        for (int i = 0; i < count; i++) {
            View childCard = mChildView.getChildAt(i);
            CardType cardType = getCardType(childCard);
            if (cardType != null && cardType == cardType.AD) {
                return true;
            }
        }
        return false;
    }

    public void replaceCardView(final View v, final CardType cardType, LinearLayout.LayoutParams layoutParams) {
        if (DEBUG) {
            Log.i(TAG, "replaceCardView");
        }
        if (v != null) {
            int index = 0;
            int count = mChildView.getChildCount();
            for (int i = 0; i < count; i++) {
                View childCard = mChildView.getChildAt(i);
                CardType cardTyp = getCardType(childCard);
                if (cardTyp != null && cardTyp == cardType.AD) {
                    index = mChildView.indexOfChild(childCard);
                }
            }
            mChildView.removeViewAt(index);
            v.setTag(R.id.super_scroll_view, cardType);
            layoutParams.leftMargin = layoutParams.rightMargin = layoutData.getCardMarginLeft();
            mChildView.addView(v, index, layoutParams);
        } else {
            if (DEBUG) {
                Log.i(TAG, "replaceCardView view为空");
                throw new IllegalArgumentException("v不能为空");
            }
        }
        handler.postDelayed(new Runnable() {

            @Override
            public void run() {
                checkScroll(v);
            }
        }, CHECK_SCROLL_DELAY_TIME);
    }

    private void checkScrollWhenRemove() {
        int oldY = getScrollY();
        int dy = 0;
        dy = getBottomScrollY() - oldY;
        if (dy < 0) {
            if (isOnlyOneChild()) {
                overScroller.startScroll(0, oldY, 0, dy);
                postInvalidate();
                View child0 = mChildView.getChildAt(0);
                if (child0 != null) {
                    notifyShowCard(true, child0);
                }
            } else {
                overScroller.startScroll(0, oldY, 0, dy);
                postInvalidate();
            }
        }
    }

    public void setChildViewAlpha(float alpha) {
        if (mChildView != null) {
            ViewHelper.setAlpha(mChildView, alpha);
        }
    }

    private void checkScroll(View addedView) {

        CardStatus cardStatus = getCardStatus();
        int oldY = getScrollY();
        int dy = 0;
        switch (cardStatus) {
        case Null:
            break;
        case OneAd: {
            if (mMobileScrollAdapter.needShowAdAll(addedView)) {
                overScroller.startScroll(0, oldY, 0, getBottomScrollY() - oldY);
                postInvalidate();
                View adCardView = findAdCardView();
                if (adCardView != null) {
                    notifyShowCard(true, adCardView);
                }
            } else {
                overScroller.startScroll(0, oldY, 0, layoutData.getShowHeadHeight() - oldY);
                postInvalidate();
                View adCardView = findAdCardView();
                if (adCardView != null) {
                    notifyShowCard(false, adCardView);
                }
            }
            break;
        }
        case OneOther: {
            overScroller.startScroll(0, oldY, 0, getBottomScrollY() - oldY);
            postInvalidate();
            View cardView = mChildView.getChildAt(0);
            if (cardView != null) {
                notifyShowCard(false, cardView);
            }
            break;
        }
        case MultipleNoScroll:
        case MultipleScroll: {
            dy = getBottomScrollY() - oldY;
            overScroller.startScroll(0, oldY, 0, dy);
            postInvalidate();
            View adCardView = findAdCardView();
            if (adCardView != null) {
                notifyShowCard(true, adCardView);
            }
            if (addedView != null) {
                notifyShowCard(true, addedView);
            }
            break;
        }
        default:
            break;
        }
    }

    private static CardType getCardType(View view) {
        if (view == null) {
            return null;
        }
        CardType cardType = null;
        Object tag = view.getTag(R.id.super_scroll_view);
        if (tag instanceof CardType) {
            cardType = (CardType) tag;
        }
        return cardType;
    }

    private View findAdCardView() {
        int count = mChildView.getChildCount();
        if (count <= 0) {
            return null;
        } else {
            for (int i = 0; i < count; i++) {
                View child = mChildView.getChildAt(i);
                CardType cardType = getCardType(child);
                if (cardType == CardType.AD) {
                    return child;
                }
            }
        }
        return null;
    }

    public Object findAdvData() {
        View adView = findAdCardView();
        if (adView != null) {
            Object o = adView.getTag(R.id.root);
            if (o != null) {
                return o;
            }
        }
        return null;
    }

    public void removeAllCardView() {
        mChildView.removeAllViews();
    }

    public boolean hasCard() {
        return mChildView.getChildCount() > 0;

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        View child = getChildAt(0);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        Resources res = getResources();
        int itemHeight = (int) res.getDimension(R.dimen.charging_show_head_card_height);
        if (height > 0) {
            LinearLayout viewGroup = (LinearLayout) child;
            viewGroup.setPadding(0, height, 0, layoutData.getOverScrollHeight());
        }
        int count = mChildView.getChildCount();
        if (count > 0) {
            for (int i = 0; i < count; i++) {
                View subChild = mChildView.getChildAt(i);
                LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) subChild.getLayoutParams();
                if (i == 0) {
                    layoutParams.topMargin = 0;
                } else {
                    layoutParams.topMargin = layoutData.getCardDividerHeight();

                }
            }
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        showHeadY = itemHeight;
        coverY = layoutData.getBottomFadeHeight();
        translateHeight = itemHeight - coverY;
        showAllY = Math.abs(child.getBottom() - child.getPaddingBottom());
        if (DEBUG) {
            Log.i(TAG, "showAllY==" + showAllY + "bottom=" + child.getBottom() + "padding=" + child.getPaddingBottom());
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
    }

    @Override
    public int getOverScrollMode() {
        return OVER_SCROLL_ALWAYS;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            dragType = DragType.No;
            needCheckDrageType = false;
            needCareMove = true;
            isFling = false;
            mLastMotionX = mDownX = ev.getX();
            mLastMotionY = mDownY = ev.getY();
            if (!overScroller.isFinished()) {
                overScroller.abortAnimation();
            }
            break;
        case MotionEvent.ACTION_MOVE:
            checkDragType(ev);
            if (dragType == DragType.No) {

            } else if (dragType == DragType.Slid) {
                slidingView = findSlidView(ev.getX(), ev.getY());
                if (slidingView != null) {
                    return true;
                }
            } else if (dragType == DragType.VerticalScroll) {
                return true;
            }
            break;

        default:
            break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    private View findSlidView(float x, float y) {
        int count = mChildView.getChildCount();
        if (count <= 0) {
            return null;
        }
        for (int i = 0; i < count; i++) {
            View child = mChildView.getChildAt(i);
            if (pointInView(x, y, child)) {
                return child;
            }

        }

        return null;
    }

    @Override
    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (DEBUG) {
            Log.i(TAG, "onTouchEvent");
        }
        boolean gestureSuc = gestureDetectorCompat.onTouchEvent(ev);
        float x = ev.getX();
        float y = ev.getY();
        int action = ev.getAction() & MotionEvent.ACTION_MASK;
        if (mChildView.getChildCount() == 0) {
            return false;
        }
        if (dragType == DragType.Slid) {
            if (action == MotionEvent.ACTION_MOVE) {
                slidChild(ev);
            } else if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
                adsorbSlid();
            }
            if (action == MotionEvent.ACTION_DOWN) {
                dragType = DragType.No;

            }
            return true;
        }
        if (isOnlyOneChild()) {
            switch (ev.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                needCheckDrageType = true;
                dragType = DragType.No;
                View childView = mChildView.getChildAt(0);
                if (!pointInView(ev.getX(), ev.getY(), childView)) {
                    if (DEBUG) {
                        Log.i(TAG, "onTouchEvent + inView");
                    }
                    return false;
                }
                return true;
            case MotionEvent.ACTION_MOVE:
                if (needCheckDrageType) {
                    checkDragType(ev);
                }
                if (DragType.Slid == dragType && !isRemoving) {
                    slidingView = findSlidView(ev.getX(), ev.getY());
                    slidChild(ev);
                    break;
                }
                if (needCareMove && getCardStatus() == CardStatus.OneAd) {
                    float deltaY = y - mDownY;
                    float abs = Math.abs(deltaY);

                    int oldScrollY = getScrollY();
                    if (abs > layoutData.getOneAdCardScrollSlop()) {
                        if (deltaY > 0) {
                            //往下滑
                            overScroller.startScroll(0, oldScrollY, 0, layoutData.getShowHeadHeight() - oldScrollY);
                            notifyShowCard(false, findAdCardView());
                        } else {
                            overScroller.startScroll(0, oldScrollY, 0, getBottomScrollY() - oldScrollY);
                            notifyShowCard(true, findAdCardView());
                        }
                        needCareMove = false;
                        postInvalidate();
                    }
                }

                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                if (slidingView != null && dragType == DragType.Slid) {
                    adsorbSlid();
                    break;
                }
                break;

            default:
                break;
            }
        } else {
            CardStatus cardStatus = getCardStatus();
            boolean canMutipleScroll = cardStatus == CardStatus.MultipleScroll;
            int oldY = getScrollY();
            int minScrollY = layoutData.getMinScrollY();
            int maxScrollY = getBottomScrollY();
            switch (ev.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                //走到这说明里面所有的view都没有点击事件
                needCheckDrageType = true;
                dragType = DragType.No;

                break;
            case MotionEvent.ACTION_MOVE:
                if (needCheckDrageType) {
                    checkDragType(ev);
                    if (dragType == DragType.Slid) {
                        slidingView = findSlidView(ev.getX(), ev.getY());
                        slidChild(ev);
                        break;
                    }
                }
                if (isFling) {
                    break;
                }

                if (!canMutipleScroll) {
                    break;
                }
                int deltaY = (int) (mLastMotionY - y);
                int newY = oldY + deltaY;
                if (newY <= minScrollY) {
                    if (oldY != minScrollY) {
                        newY = minScrollY;
                        scrollTo(0, newY);
                        onScrollChanged(0, newY, 0, oldY);
                    }
                } else if (newY >= getScrollRange()) {
                    if (oldY != getScrollRange()) {
                        newY = getScrollRange();
                        scrollTo(0, newY);
                        onScrollChanged(0, newY, 0, oldY);
                    }
                } else {
                    scrollTo(0, newY);
                    onScrollChanged(0, newY, 0, oldY);
                }

                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                if (isFling) {
                    break;
                } else if (slidingView != null && dragType == DragType.Slid) {
                    adsorbSlid();
                    break;

                } else if (canMutipleScroll) {
                    int topOverScrollY = layoutData.getScrollViewHeight() - oldY;
                    int bottomOverScrollY = maxScrollY - oldY;

                    if (DEBUG) {
                        Log.d(TAG, "up " + oldY + "," + topOverScrollY + "," + bottomOverScrollY);
                    }
                    if (topOverScrollY > 0) {
                        overScroller.springBack(0, oldY, 0, 0, layoutData.getScrollViewHeight(), getBottomScrollY());
                    } else if (bottomOverScrollY < 0) {
                        overScroller.springBack(0, oldY, 0, 0, layoutData.getScrollViewHeight(), getBottomScrollY());
                    }
                    postInvalidate();
                }
                break;

            default:
                break;
            }
        }
        mLastMotionY = y;
        mLastMotionX = x;
        return true;
    }

    private void notifyShowCard(boolean isShowAll, View child) {
        if (DEBUG) {
            Log.i(TAG, "notifyShowCard");
        }
        if (mMobileScrollAdapter == null || child == null) {
            return;
        }
        if (isShowAll) {
            mMobileScrollAdapter.onCardShowAll(child, getCardType(child));
        } else {
            mMobileScrollAdapter.onCardShowHead(child, getCardType(child));
        }
    }

    private void removeViewAni(final boolean open) {
        if (slidingView == null) {
            return;
        }
        isRemoving = true;
        float tx = ViewHelper.getTranslationX(slidingView);
        final float targetX = tx < 0 ? -getMeasuredWidth() : getMeasuredWidth();
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(tx, targetX);
        valueAnimator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float value = (Float) valueAnimator.getAnimatedValue();
                translatX(slidingView, value);

            }
        });
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);

                mChildView.removeView(slidingView);
                notifyListenerRemove(slidingView);

                slidingView = null;
                handler.postDelayed(new Runnable() {

                    @Override
                    public void run() {
                        checkScrollWhenRemove();
                        isRemoving = false;
                    }

                }, CHECK_SCROLL_DELAY_TIME);
            }
        });
        final View v = slidingView;
        valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
            boolean opened = false;

            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float value = (Float) valueAnimator.getAnimatedValue();
                if (open && !opened && value > targetX / 3) {
                    opened = true;
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            mMobileScrollAdapter.onOpenAd(v);
                        }
                    });
                }
            }
        });
        valueAnimator.setDuration(300);
        valueAnimator.start();

    }

    private void notifyListenerRemove(View v) {
        if (mMobileScrollAdapter != null) {
            CardType cardType = getCardType(v);
            mMobileScrollAdapter.onRemove(v, cardType);
        }
    }

    private void adsorbSlid() {
        if (slidingView == null) {
            return;
        }
        float translateX = ViewHelper.getTranslationX(slidingView);

        if (!canSlidDelete(slidingView)) {
            translatX(slidingView, 0);
            return;
        }
        if (Math.abs(translateX) > layoutData.getSlidDelete()) {
            CardType type = getCardType(slidingView);
            //往右滑
            if (type != CardType.AD || translateX < 0) {
                removeViewAni(false);
            } else {

                removeViewAni(true);
                //                handler.postDelayed(new Runnable() {
                //
                //                    @Override
                //                    public void run() {
                //                        translatX(slidingView, 0);
                //                    }
                //                }, 1000);
            }
        } else {
            translatX(slidingView, 0);
        }

    }

    private void translatX(View slidingView, float x) {
        if (slidingView != null) {
            ViewHelper.setTranslationX(slidingView, x);
        }
        invalidate();
    }

    private void slidChild(MotionEvent ev) {
        if (slidingView != null) {
            float x = ev.getX() - mDownX;
            translatX(slidingView, x);
        }
    }

    private boolean pointInView(float x, float y, View v) {
        float localX = x + getScrollX() - v.getLeft();
        float localY = y + getScrollY() - v.getTop();
        return localX >= 0 && localX < (v.getRight() - v.getLeft()) && localY >= 0
                && localY < (v.getBottom() - v.getTop());
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (showAllY == 0) {
            return;
        }
        if (mMobileScrollAdapter != null) {
            scrollInfo.currentCardStatus = getCardStatus();
            scrollInfo.value = getScrollY() * 1f / showAllY;
            scrollInfo.showAllValue = layoutData.getScrollViewHeight() * 1f / showAllY;
            scrollInfo.coverValue = coverY * 1f / showAllY;
            scrollInfo.showHeadValue = showHeadY * 1f / showAllY;
            scrollInfo.translateHeight = translateHeight;
            scrollInfo.scrollTopLine = layoutData.getScrollViewHeight();
            scrollInfo.scrollBottomLine = getBottomScrollY();
            scrollInfo.scrollY = t;
            mMobileScrollAdapter.onScroll(scrollInfo);
            if (DEBUG) {
                Log.d(TAG, scrollInfo.toString());
            }
        }
    }

    @Override
    public boolean onDown(MotionEvent e) {

        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    private boolean isOnlyOneChild() {
        return mChildView.getChildCount() == 1;
    }

    public CardStatus getCardStatus() {
        CardStatus result = CardStatus.Null;
        int count = mChildView.getChildCount();
        if (count <= 0) {
            return result;
        } else if (count > 0 && count <= 1) {
            View child = mChildView.getChildAt(0);
            CardType cardType = getCardType(child);
            if (cardType == CardType.AD) {
                return CardStatus.OneAd;
            } else if (cardType == null) {
                return CardStatus.Null;
            } else {
                return CardStatus.OneOther;
            }

        } else {
            int height = mChildView.getBottom() - mChildView.getTop() - mChildView.getPaddingBottom()
                    - mChildView.getPaddingTop();
            if (height > layoutData.getScrollViewHeight()) {
                return CardStatus.MultipleScroll;
            } else {
                return CardStatus.MultipleNoScroll;
            }
        }

    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

        return false;

    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

        if (dragType != DragType.VerticalScroll) {
            return false;
        }
        if (getCardStatus() != CardStatus.MultipleScroll) {
            return false;
        }
        float oldY = getScrollY();
        if (velocityY > 0) {
            if (oldY <= layoutData.getMinScrollY()) {
                return false;
            }
        } else if (velocityY < 0) {
            if (oldY >= getScrollRange()) {
                return false;
            }
        }
        isFling = true;
        int minScrollY = layoutData.getScrollViewHeight();
        int maxScrollY = getBottomScrollY();
        overScroller.fling(0, (int) oldY, 0, (int) -velocityY, 0, 0, minScrollY, maxScrollY, 0,
                layoutData.getOverScrollHeight());
        invalidate();

        return true;
    }

    public void setMobileScrollAdapter(MobileScrollAdapter mobileScrollAdapter) {
        this.mMobileScrollAdapter = mobileScrollAdapter;
    }

    private boolean canSlidDelete(View v) {
        if (mMobileScrollAdapter == null || v == null) {
            return true;
        }
        return mMobileScrollAdapter.canSlidDelete(v);

    }

    public interface OnMobileScrollViewScroll {

        void onScroll(ScrollInfo scrollInfo);

        void onOpenAd(View slidingView);

        void onRemove(View v, CardType cardType);

        void onCardShowAll(View v, CardType cardType);

        void onCardShowHead(View v, CardType cardType);

    }

    public interface MobileScrollAdapter extends OnMobileScrollViewScroll {
        boolean canSlidDelete(View v);

        boolean needShowAdAll(View v);
    }

    public static class ScrollInfo {
        public int scrollY;
        public float value, coverValue, showHeadValue, showAllValue, translateHeight, cardHeight;

        /**
         * 最低线，如果scrollY>=bottomLine就隐藏底下的渐变
         */
        public float scrollBottomLine;
        /**
         * 最高线，如果scrollY<topLine 就显示上端的渐变线
         */
        public float scrollTopLine;
        public CardStatus currentCardStatus;

        @Override
        public String toString() {
            return "ScrollInfo [scrollY=" + scrollY + ", value=" + value + ", coverValue=" + coverValue
                    + ", showHeadValue=" + showHeadValue + ", showAllValue=" + showAllValue + ", translateHeight="
                    + translateHeight + ", cardHeight=" + cardHeight + ", scrollBottomLine=" + scrollBottomLine
                    + ", scrollTopLine=" + scrollTopLine + ", currentCardStatus=" + currentCardStatus + "]";
        }

        public ScrollInfo() {

        }

        public ScrollInfo(float value, float coverValue, CardStatus currentCardStatus, float showHeadValue,
                float showAllValue, float translateHeight) {
            this.value = value;
            this.coverValue = coverValue;
            this.currentCardStatus = currentCardStatus;
            this.showHeadValue = showHeadValue;
            this.showAllValue = showAllValue;
            this.translateHeight = translateHeight;
        }

    }

    private int getScrollRange() {
        int scrollRange = 0;
        if (getChildCount() > 0) {
            scrollRange = Math.max(0, mChildView.getHeight() - (getHeight() - getPaddingBottom() - getPaddingTop()));
        }
        return scrollRange;
    }

    private int getBottomScrollY() {
        return getScrollRange() - layoutData.getOverScrollHeight();
    }

    @Override
    public void computeScroll() {
        boolean needScroll = overScroller.computeScrollOffset();
        if (DEBUG) {
            Log.d(TAG, "needScroll:" + needScroll);
        }
        if (needScroll) {
            int oldX = getScrollX();
            int oldY = getScrollY();
            int x = overScroller.getCurrX();
            int y = overScroller.getCurrY();
            if (DEBUG) {
                Log.d(TAG, "overScroller.getCurrY()" + overScroller.getCurrY());
            }
            scrollTo(x, y);
            onScrollChanged(getScrollX(), getScrollY(), oldX, oldY);
            postInvalidate();
        }

    }

    private void checkDragType(MotionEvent event) {
        float delatX = Math.abs(event.getX() - mDownX);
        float delatY = Math.abs(event.getY() - mDownY);
        if (dragType != DragType.No) {
            return;
        }
        if (delatX > configuration.getScaledTouchSlop() && delatX * 0.5f > delatY && !isRemoving) {
            dragType = DragType.Slid;
        } else if (delatY > configuration.getScaledTouchSlop()) {
            dragType = DragType.VerticalScroll;
        }

    }
}
